package com.sxf.djiuav;

import dji.sdk.keyvalue.key.CameraKey;
import dji.sdk.keyvalue.key.KeyTools;
import dji.sdk.keyvalue.value.camera.CameraStorageLocation;
import dji.sdk.keyvalue.value.common.ComponentIndexType;
import dji.sdk.keyvalue.value.common.EmptyMsg;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.ErrorImp;
import dji.v5.common.error.ErrorType;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.KeyManager;
import dji.v5.manager.datacenter.media.MediaFile;
import dji.v5.manager.datacenter.media.MediaFileDownloadListener;
import dji.v5.manager.datacenter.media.MediaFileListDataSource;
import dji.v5.manager.datacenter.media.MediaManager;
import dji.v5.manager.datacenter.media.PullMediaFileListParam;
import dji.v5.utils.common.ContextUtil;
import dji.v5.utils.common.DiskUtil;
import dji.v5.utils.common.LogUtils;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import jcifs.CIFSContext;
import jcifs.Configuration;
import jcifs.config.PropertyConfiguration;
import jcifs.context.BaseContext;
import jcifs.smb.NtlmPasswordAuthenticator;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileOutputStream;

/**
 * MediaHelper - 提供媒体文件操作的辅助类
 * 功能：下载所有照片/视频文件，删除所有照片/视频文件，上传文件到SMB服务器
 */
public class MediaHelper {
    private static final String TAG = "MediaHelper";
    private ComponentIndexType cameraIndex;
    private CameraStorageLocation storageLocation;
    private CommonCallbacks.CompletionCallback operationCallback;
    private DJIApplication app = null;
    private CIFSContext context;
    private String smbPath;
    
    /**
     * 构造函数
     * @param cameraIndex 相机索引
     * @param storageLocation 存储位置
     */
    public MediaHelper(DJIApplication app, ComponentIndexType cameraIndex, CameraStorageLocation storageLocation, String ip, String domain, String username, String password) {
        this.app = app;
        this.cameraIndex = cameraIndex;
        this.storageLocation = storageLocation;
        new Thread(() -> {
            try {
                Configuration config = new PropertyConfiguration(System.getProperties());
                context = new BaseContext(config);
                NtlmPasswordAuthenticator auth = new NtlmPasswordAuthenticator(domain, username, password);
                context = context.withCredentials(auth);
                this.smbPath = "smb://" + ip + "/public/";
            } catch (Exception e) {
                LogUtils.e(TAG, "MediaHelper: " + e.toString());
                app.addLog("MediaHelper: " + e.toString());
            }
        }).start();
    }
    
    /**
     * 设置操作回调
     * @param callback 回调接口
     */
    public void setOperationCallback(CommonCallbacks.CompletionCallback callback) {
        this.operationCallback = callback;
    }
    
    /**
     * 下载所有媒体文件
     */
    public void downloadAllMediaFiles() {
        // 设置数据源
        MediaFileListDataSource dataSource = new MediaFileListDataSource.Builder()
                .setIndexType(cameraIndex)
                .setLocation(storageLocation)
                .build();
        MediaManager.getInstance().setMediaFileDataSource(dataSource);
        // 拉取媒体文件列表
        MediaManager.getInstance().pullMediaFileListFromCamera(
                new PullMediaFileListParam.Builder().count(-1).build(),
                new CommonCallbacks.CompletionCallback() {
                    @Override
                    public void onSuccess() {
                        // 获取媒体文件列表
                        List<MediaFile> mediaFiles = MediaManager.getInstance().getMediaFileListData().getData();
                        if (mediaFiles == null || mediaFiles.isEmpty()) {
                            notifyOperationResult(true, "没有找到媒体文件");
                            return;
                        }
                        // 下载所有文件
                        downloadFiles(mediaFiles, 0);
                    }
                    @Override
                    public void onFailure(IDJIError error) {
                        notifyOperationResult(false, "获取媒体文件列表失败: " + error.description());
                    }
                }
        );
    }
    /**
     * 递归下载文件
     * @param mediaFiles 媒体文件列表
     * @param index 当前下载的文件索引
     */
    private void downloadFiles(List<MediaFile> mediaFiles, int index) {
        if (index >= mediaFiles.size()) {
            notifyOperationResult(true, "所有文件下载完成");
            return;
        }
        MediaFile mediaFile = mediaFiles.get(index);
        downloadFile(mediaFile, new CommonCallbacks.CompletionCallback() {
            @Override
            public void onSuccess() {
                // 下载成功后继续下载下一个文件
                downloadFiles(mediaFiles, index + 1);
            }
            @Override
            public void onFailure(IDJIError error) {
                notifyOperationResult(false, "下载文件失败: " + mediaFile.getFileName() + ", 错误: " + error.description());
            }
        });
    }
    
    /**
     * 下载单个文件
     * @param mediaFile 媒体文件
     * @param callback 回调接口
     */
    private void downloadFile(MediaFile mediaFile, CommonCallbacks.CompletionCallback callback) {
        try {
            SmbFile smbFile = new SmbFile(smbPath+mediaFile.getFileName(), context);
            OutputStream out = new SmbFileOutputStream(smbFile);
            BufferedOutputStream bos = new BufferedOutputStream(out, 524288);//4194304/2097152/1048576/524288/262144
            // 开始下载
            mediaFile.pullOriginalMediaFileFromCamera(0, new MediaFileDownloadListener() {
                private long lastProgressUpdateTime = 0;
                private long totalS = 0;
                private static final long PROGRESS_UPDATE_INTERVAL = 500; // 每500ms更新一次进度
                @Override
                public void onStart() {
                    String msg = "开始下载文件: " + mediaFile.getFileName();
                    LogUtils.i(TAG, msg);
                    app.addLog(msg);
                }
                @Override
                public void onProgress(long total, long current) {
                    // 限制进度更新频率
                    long currentTime = System.currentTimeMillis();
                    if (currentTime - lastProgressUpdateTime > PROGRESS_UPDATE_INTERVAL || current == total) {
                        totalS = total;
                        // 计算下载进度
                        double progress = (double) current / total * 100;
                        LogUtils.i(TAG, "文件下载进度: " + mediaFile.getFileName() + " - " + String.format("%.2f", progress) + "%");
                        lastProgressUpdateTime = currentTime;
                    }
                }
                @Override
                public void onRealtimeDataUpdate(byte[] data, long position) {
                    try {
                        bos.write(data);
                    } catch (IOException e) {
                        String msg = "写入文件错误: " + e.getMessage();
                        LogUtils.i(TAG, msg);
                        app.addLog(msg);
                    }
                }
                @Override
                public void onFinish() {
                    new Thread(() -> {
                        try {
                            bos.flush();
                            bos.close();
                        } catch (IOException e) {
                            String msg = "关闭流错误: " + e.getMessage();
                            LogUtils.i(TAG, msg);
                            app.addLog(msg);
                        }
                        String msg = "文件下载完成: " + mediaFile.getFileName();
                        LogUtils.i(TAG, msg);
                        app.addLog(msg);
                        callback.onSuccess();
                    }).start();
                }
                @Override
                public void onFailure(IDJIError error) {
                    new Thread(() -> {
                        try {
                            bos.flush();
                            bos.close();
                        } catch (IOException e) {
                            String msg = "文件下载错误: " + e.getMessage();
                            LogUtils.i(TAG, msg);
                            app.addLog(msg);
                        }
                        app.addLog("文件下载错误");
                        callback.onFailure(error);
                    }).start();
                }
            });
        } catch (IOException e) {
            LogUtils.e(TAG, "创建文件输出流错误: " + e.getMessage());
            callback.onFailure(createCustomError("创建文件输出流错误: " + e.getMessage()));
        }
    }
    
    /**
     * 删除所有媒体文件
     */
    public void deleteAllMediaFiles() {
        // 设置数据源
        MediaFileListDataSource dataSource = new MediaFileListDataSource.Builder()
                .setIndexType(cameraIndex)
                .setLocation(storageLocation)
                .build();
        MediaManager.getInstance().setMediaFileDataSource(dataSource);
        // 拉取媒体文件列表
        MediaManager.getInstance().pullMediaFileListFromCamera(
                new PullMediaFileListParam.Builder().count(-1).build(),
                new CommonCallbacks.CompletionCallback() {
                    @Override
                    public void onSuccess() {
                        // 获取媒体文件列表
                        List<MediaFile> mediaFiles = MediaManager.getInstance().getMediaFileListData().getData();
                        if (mediaFiles == null || mediaFiles.isEmpty()) {
                            notifyOperationResult(true, "没有找到媒体文件");
                            return;
                        }
                        // 删除所有文件
                        deleteFiles(new ArrayList<>(mediaFiles));
                    }
                    @Override
                    public void onFailure(IDJIError error) {
                        notifyOperationResult(false, "获取媒体文件列表失败: " + error.description());
                    }
                }
        );
    }
    
    /**
     * 删除文件
     * @param mediaFiles 媒体文件列表
     */
    private void deleteFiles(List<MediaFile> mediaFiles) {
        MediaManager.getInstance().deleteMediaFiles(mediaFiles,
                new CommonCallbacks.CompletionCallback() {
                    @Override
                    public void onSuccess() {
                        notifyOperationResult(true, "成功删除 " + mediaFiles.size() + " 个文件");
                    }
                    @Override
                    public void onFailure(IDJIError error) {
                        notifyOperationResult(false, "删除文件失败: " + error.description());
                    }
                });
    }
    
    /**
     * 格式化SD卡
     */
    public void formatSDCard() {
        KeyManager.getInstance().performAction(
                KeyTools.createKey(CameraKey.KeyFormatStorage),
                CameraStorageLocation.SDCARD,
                new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
                    @Override
                    public void onSuccess(EmptyMsg result) {
                        notifyOperationResult(true, "SD卡格式化成功");
                    }
                    @Override
                    public void onFailure(IDJIError error) {
                        notifyOperationResult(false, "SD卡格式化失败: " + error.description());
                    }
                }
        );
    }
    
    /**
     * 通知操作结果
     * @param success 是否成功
     * @param message 消息内容
     */
    private void notifyOperationResult(boolean success, String message) {
        if (operationCallback != null) {
            if (success) {
                operationCallback.onSuccess();
            } else {
                operationCallback.onFailure(createCustomError(message));
            }
        }
        LogUtils.i(TAG, message);
        app.addLog(message);
    }
    
    /**
     * 创建自定义错误
     * @param message 错误消息
     * @return IDJIError 实例
     */
    private IDJIError createCustomError(String message) {
        return new ErrorImp(ErrorType.UNKNOWN, "", "", "", message);
    }
}
